﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Drawing;
using TranslationProjectBuilder.Windows;
using TranslationProjectBuilder.Windows.Forms;

namespace TranslationProjectBuilder
{
    public partial class Form1 : Form
    {
        private DirectoryInfo rootDirectoryInfo;
        private DirectoryInfo rootExportDirectoryInfo;

        private String[] allowedFileKey = { "*.resx" };
        private String[] cleanUpKey = { "*.no.resx" };

        private Dictionary<String, String> languageFiles;
        private Dictionary<string, FileTreeView> fileTreeViews = new Dictionary<string, FileTreeView>();

        private Font fontFileTreeViewFolder;
        private Color colorFileTreeViewVisited;

        public Form1()
        {
            InitializeComponent();
            fontFileTreeViewFolder = new Font("Arial", 8, FontStyle.Italic);
            colorFileTreeViewVisited = Color.Blue;
        }

        /*
         *      Menu: File -> Open
         */
        private void newProjectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (FolderBrowserDialog dlg = new FolderBrowserDialog())
            {
                dlg.Description = "Select project folder to open";

                if (dlg.ShowDialog() == DialogResult.OK)
                {
                    if (tabControl.TabCount > 0)
                    {
                        foreach (TabPage tabPage in tabControl.TabPages)
                        {
                            fileTreeViews[tabPage.Text] = null;
                            fileTreeViews.Remove(tabPage.Text);
                            tabControl.TabPages.Remove(tabPage);
                        }

                    }

                    rootDirectoryInfo = new DirectoryInfo(dlg.SelectedPath);

                    fileTreeView.loadContent(dlg.SelectedPath, allowedFileKey);
                    TreeNodeFormat.ChangeParentFont(fontFileTreeViewFolder, fileTreeView.getNodes());

                    //Clean up empty nodes
                    removeStubs();

                    //Remove unwanted files as listen by String[] cleanUpKey
                    TreeNodeCollection nodes = fileTreeView.getNodes();
                    removeUnwantedFiles(ref nodes);
                }
            }
        }

        /* 
         *      Menu: File -> Export All
         */
        private void exportAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (FolderBrowserDialog dlg = new FolderBrowserDialog())
            {
                dlg.Description = "Select output folder";

                if (dlg.ShowDialog() == DialogResult.OK)
                {
                    rootExportDirectoryInfo = new DirectoryInfo(dlg.SelectedPath);

                    foreach (TabPage tabPage in tabControl.TabPages)
                    {
                        createDirectory(rootExportDirectoryInfo.FullName + @"\" + tabPage.Text);
                        exportTreeNode("", tabPage.Text, fileTreeViews[tabPage.Text].getNodes());
                    }
                }
            }
        }

        /*
         *      Menu: File -> Exit
         */
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        /*
         *      Menu: Project Tab -> New
         */
        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (InputBox ib = new InputBox("New Tab", "Enter new tab name:", "tab" + (tabControl.TabCount + 1)))
            {
                if (ib.showInputBox() == DialogResult.OK)
                {
                    string title = ib.Output;

                    if (checkUniqueTabName(title))
                    {
                        TabPage newTabPage = new TabPage(title);
                        FileTreeView newFileTreeView = new FileTreeView();
                        newFileTreeView.Dock = DockStyle.Fill;

                        fileTreeViews.Add(title, newFileTreeView);
                        newTabPage.Controls.Add(newFileTreeView);
                        tabControl.TabPages.Add(newTabPage);
                    }
                }
                else
                {

                }
            }
        }

        /*
         *      Menu: Project Tabs -> Rename
         */
        private void renameToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (tabControl.TabCount > 0)
            {
                using (InputBox ib = new InputBox("Rename", "Enter new name:", tabControl.SelectedTab.Text))
                {
                    if (ib.showInputBox() == DialogResult.OK)
                    {
                        string title = ib.Output;

                        if (checkUniqueTabName(title))
                        {
                            FileTreeView tmp = fileTreeViews[tabControl.SelectedTab.Text];
                            fileTreeViews.Remove(tabControl.SelectedTab.Text);
                            fileTreeViews.Add(title, tmp);
                            tabControl.SelectedTab.Text = title;
                        }
                    }
                }
            }
        }

        /*
         *      Menu: Tab -> Export
         */
        private void exportToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (FolderBrowserDialog dlg = new FolderBrowserDialog())
            {
                dlg.Description = "Select output folder";

                if (dlg.ShowDialog() == DialogResult.OK)
                {
                    rootExportDirectoryInfo = new DirectoryInfo(dlg.SelectedPath);
                    TabPage tabPage = tabControl.SelectedTab;
                    createDirectory(rootExportDirectoryInfo.FullName + @"\" + tabPage.Text);
                    exportTreeNode("", tabPage.Text, fileTreeViews[tabPage.Text].getNodes());
                }
            }
        }

        /*
         *      Menu: Tab -> Remove
         */
        private void removeToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            if (tabControl.TabCount > 0)
            {
                fileTreeViews[tabControl.SelectedTab.Text] = null;
                fileTreeViews.Remove(tabControl.SelectedTab.Text);

                tabControl.TabPages.Remove(tabControl.SelectedTab);
            }
        }

        /*
         *      Button: ">>"; Add
         */
        private void buttonAdd_Click(object sender, EventArgs e)
        {
            if (tabControl.TabCount > 0)
            {
                TreeNode selectedItem = fileTreeView.getSelectedNode();
                fileTreeViews[tabControl.SelectedTab.Text].insertNode(ref selectedItem);

                //selectedItem.ForeColor = colorFileTreeViewVisited;
                //TreeNodeFormat.ChangeSubTreeColor(colorFileTreeViewVisited, selectedItem.Nodes);
            }
        }

        /*
         *      Button: "<<"; Remove
         */
        private void buttonRemove_Click(object sender, EventArgs e)
        {
            if (tabControl.TabCount > 0)
            {
                TreeNode selectedItem = fileTreeView.getSelectedNode();
                fileTreeViews[tabControl.SelectedTab.Text].removeNode();

                //selectedItem.ForeColor = Color.Black;
                //TreeNodeFormat.ChangeSubTreeColor(colorFileTreeViewVisited, selectedItem.Nodes);
            }
        }
        
        /*
         *      void exportTreeNode(string path, string tabName, TreeNodeCollection tnCollection)
         *      Export helper method
         */
        private void exportTreeNode(string path, string tabName, TreeNodeCollection tnCollection)
        {
            foreach (TreeNode node in tnCollection)
            {
                if (node.Nodes.Count > 0)
                {
                    // Folder
                    // Will currently crash if exporting an empty folder!
                    String folderPath = path + @"\" + node.Text;
                    createDirectory(rootExportDirectoryInfo.FullName + @"\" + tabName + @"\" + folderPath);
                    exportTreeNode(folderPath, tabName, node.Nodes);
                }
                else
                {
                    // File
                    String sourceFile = rootDirectoryInfo.FullName + path + @"\" + node.Text;
                    String destFile = rootExportDirectoryInfo.FullName + @"\" + tabName + path + @"\" + node.Text;
                    System.IO.File.Copy(sourceFile, destFile, true);
                }
            }
        }

        /*
         *      Create a Folder
         */
        private void createDirectory(string path)
        {
            if (!System.IO.Directory.Exists(path))
            {
                System.IO.Directory.CreateDirectory(path);
            }
        }

        /*
         *      bool checkUniqueTabName(String name)
         *      Check if a Tab-name is Unique, this is used when creating a new Tab or renaming one
         */
        private bool checkUniqueTabName(String name)
        {
            foreach (TabPage tabPage in tabControl.TabPages)
            {
                if (name == tabPage.Text)
                {
                    MessageBox.Show("This name is already in use.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return false;
                }
            }
            return true;
        }

        /*
         *      removeUnwantedFiles(ref TreeNodeCollection tnCollection)
         *      Removes unwanted files from tnCollection as specified in private String[] cleanUpKey
         */
        private void removeUnwantedFiles(ref TreeNodeCollection tnCollection)
        {
            foreach (TreeNode node in tnCollection)
            {
                if (node != null)
                {
                    if (filenameSuffix(node.Text, cleanUpKey))
                    {
                        node.Remove();
                    }
                    else if (node.Nodes != null)
                    {
                        TreeNodeCollection nodes = node.Nodes;
                        removeUnwantedFiles(ref nodes);
                    }
                }
            }
        }

        /* 
         *      removeStubs() Method to remove empty folders, this is the one you want to call from Form1.cs and calls 
         *      removeStubs(ref TreeNodeCollection tnCollection) until no more updates have been done.
         */
        private void removeStubs()
        {
            bool update = true;

            while (update)
            {
                TreeNodeCollection nodes = fileTreeView.getNodes();
                update = removeStubs(ref nodes);
            }
        }

        /*
         *      Called by removeStubs() and returns true if a stub has been removed
         *      a stub is removed if the TreeNode.Nodes == null or TreeNode.Nodes.Count == 0
         *      if the TreeNode isn't empty the method will call itself recursively with removeStubs(TreeNode.Nodes)
         *      this also means only the outmost empty branches will be removed and hence the while-loop in removeStubs()
         *      Can probably be done much more efficent.
         */
        private bool removeStubs(ref TreeNodeCollection tnCollection)
        {
            bool removed = false;

            foreach (TreeNode node in tnCollection)
            {
                if (node != null)
                {
                    if (node.Nodes == null)
                    {
                        if (filenameSuffix(node.Text, allowedFileKey) == false)
                        {
                            node.Remove();
                            removed = true;
                        }
                    }
                    else
                    {
                        if (node.Nodes.Count == 0)
                        {
                            if (filenameSuffix(node.Text, allowedFileKey) == false)
                            {
                                node.Remove();
                                removed = true;
                            }
                        }
                        else
                        {
                            TreeNodeCollection nodes = node.Nodes;
                            if (removeStubs(ref nodes))
                                removed = true;
                        }
                    }
                }
            }
            return removed;
        }

        /*
         *      filenNameSuffix(string, string[]) returns true if the filename has one of the suffixes in keys[]
         *      still need to add so that filename.language.resx does not return true for ".resx"
         */
        private bool filenameSuffix(string filename, string[] keys)
        {
            foreach (String key in keys)
            {
                bool match = true;

                if (key.Length <= filename.Length)
                {
                    for (int i = 0; i < key.Length - 1; i++)
                    {
                        if (filename[filename.Length - 1 - i] != key[key.Length - 1 - i])
                        {
                            match = false;
                        }
                    }
                    if (match)
                        return true;
                }
            }
            return false;
        }

    }
}
